﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TaskExtensions.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Defines the TaskExtensions type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Threading
{
    using System;

    public static class TaskExtensions
    {
        public static ITask ContinueWith(this ITask instance,
           ITask child)
        {
            return instance.ContinueWith(child, null, null);
        }

        public static ITask ContinueWith(this ITask instance,
           ITask continuationTask, TaskCallBack callBack)
        {
            return instance.ContinueWith(continuationTask, callBack, null);
        }

        public static ITask ContinueWith(this ITask instance,
           ITask continuationTask, TaskCallBack callBack, object userState)
        {
            #region Validate Arguments

            if (continuationTask == null)
            {
                throw new ArgumentNullException("continuationTask");
            }

            #endregion

            continuationTask.ContinueFrom(instance.ContinuationSource, callBack, userState);
            return continuationTask;
        }
        
        private static ITask<T> ContinueWithCore<T>(ITask parent,
           ITask<T> child, TaskCallBack<T> callBack, object userState)
        {
            child.ContinueFrom(parent.ContinuationSource, t =>
                {
                    if (callBack != null)
                    {
                        callBack((ITask<T>)t);
                    }
                }, userState);
            return child;
        }

        public static ITask ContinueWith(this ITask instance, Action action,
           TaskFactory factory, TaskCallBack callBack)
        {
            return ContinueWith(instance, factory.From(action), callBack, null);
        }

        public static ITask ContinueWith(this ITask instance, Action action,
           TaskFactory factory)
        {
            return ContinueWith(instance, factory.From(action), null, null);
        }

        public static ITask ContinueWith<TParent>(this ITask<TParent> instance,
           Action<ITask<TParent>> action, TaskFactory factory)
        {
            return ContinueWith(instance, factory.From(action, instance), null, null);
        }

        public static ITask ContinueWith<TParent>(this ITask<TParent> instance,
             Action<ITask<TParent>> action, TaskCallBack callBack, TaskFactory factory)
        {
            return ContinueWith(instance, factory.From(action, instance), callBack, null);
        }

        public static ITask ContinueWith(this ITask instance,
             Action<ITask> action, TaskCallBack callBack, TaskFactory factory)
        {
            return ContinueWith(instance, factory.From(action, instance), callBack, null);
        }

        public static ITask<TChild> ContinueWith<TParent, TChild>(this ITask<TParent> instance,
           Func<ITask<TParent>, TChild> func, TaskCallBack<TChild> callBack, TaskFactory factory)
        {
            return ContinueWithCore(instance, factory.From(func, instance), callBack, null);
        }

        public static ITask<TChild> ContinueWith<TParent, TChild>(this ITask<TParent> instance,
           Func<ITask<TParent>, TChild> func, TaskFactory factory)
        {
            return ContinueWithCore(instance, factory.From(func, instance), null, null);
        }

        #region Start Extensions

        public static void Start(this ITask instance)
        {
            instance.Start(null, null);
        }

        public static void Start(this ITask instance, TaskCallBack callBack)
        {
            instance.Start(callBack, null);
        }

        public static void Start<TReturn>(this ITask<TReturn> instance, TaskCallBack<TReturn> callBack)
        {
            instance.Start(callBack, null);
        }

        #endregion
    }
}
